import javax.sound.sampled.*;
import java.io.*;
import java.net.*;

/**
 * @author weixia.tian
 */
public class Mic {

    public static class Record implements Runnable {
        //定义存放录音的字节数组,作为缓冲区
        byte bts[] = new byte[10000];
        FileOutputStream baos = null;

        TargetDataLine td = null;
        DatagramSocket socket = null;

        Record(TargetDataLine td, DatagramSocket socket) {
            this.td = td;
            this.socket = socket;
        }

        //将字节数组包装到流里，最终存入到baos中
        //重写run函数
        public void run() {
            try {
                baos = new FileOutputStream("/home/devlap/project/vad/test.pcm");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            try {
                System.out.println("ok3");
                while (true) {
                    //当停止录音没按下时，该线程一直执行
                    //从数据行的输入缓冲区读取音频数据。
                    //要读取bts.length长度的字节,cnt 是实际读取的字节数
                    int cnt = td.read(bts, 0, bts.length);
                    if (cnt > 0) {
                        InetAddress ip = InetAddress.getByName("127.0.0.1");//接收内容的Ip地址
                        DatagramPacket packet = new DatagramPacket(bts, bts.length, ip, 1235); //创建要发送的数据包，然后用套接字发送
                        socket.send(packet);
                        baos.write(bts, 0, cnt);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    //关闭打开的字节数组流
                    if (baos != null) {
                        baos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    td.drain();
                    td.close();
                }
            }
        }
    }

    public static void main(String... args) {
        //定义录音格式
        AudioFormat af = null;
        //定义目标数据行,可以从中读取音频数据,该 TargetDataLine 接口提供从目标数据行的缓冲区读取所捕获数据的方法。
        TargetDataLine td = null;
        //定义源数据行,源数据行是可以写入数据的数据行。它充当其混频器的源。应用程序将音频字节写入源数据行，这样可处理字节缓冲并将它们传递给混频器。
        SourceDataLine sd = null;
        //定义字节数组输入输出流
        ByteArrayInputStream bais = null;
        ByteArrayOutputStream baos = null;
        //定义音频输入流
        AudioInputStream ais = null;
        //定义停止录音的标志，来控制录音线程的运行
        Boolean stopflag = false;
        try {

            DatagramSocket socket = new DatagramSocket(7777);//创建一个发送消息的套接字

            //af为AudioFormat也就是音频格式
            af = getAudioFormat();
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
            td = (TargetDataLine) (AudioSystem.getLine(info));
            //打开具有指定格式的行，这样可使行获得所有所需的系统资源并变得可操作。
            td.open(af);
            //允许某一数据行执行数据 I/O
            td.start();

            //创建播放录音的线程
            Record record = new Record(td, socket);
            Thread t1 = new Thread(record);
            t1.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static AudioFormat getAudioFormat() {
        //下面注释部分是另外一种音频格式，两者都可以
        AudioFormat.Encoding encoding = AudioFormat.Encoding.
                PCM_SIGNED;
        float rate = 16000f;
        int sampleSize = 16;
        boolean bigEndian = false;
        int channels = 1;
        return new AudioFormat(encoding, rate, sampleSize, channels,
                (sampleSize / 8) * channels, rate, bigEndian);
//		//采样率是每秒播放和录制的样本数
//		float sampleRate = 16000.0F;
//		// 采样率8000,11025,16000,22050,44100
//		//sampleSizeInBits表示每个具有此格式的声音样本中的位数
//		int sampleSizeInBits = 16;
//		// 8,16
//		int channels = 1;
//		// 单声道为1，立体声为2
//		boolean signed = true;
//		// true,false
//		boolean bigEndian = true;
//		// true,false
//		return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,bigEndian);
    }
}
